        public bool DumpRom(int firstAddress, int lastAddress)
        {
            const ushort BLOCK_SIZE = 0x0100;   // 256 bytes per block
            const byte MAX_CHUNK = 13;          // protocol limit
            const bool DEBUG = true;

            if (firstAddress < 0 || lastAddress < 0 || lastAddress < firstAddress)
            {
                Logger.Write("ReadRomEepromBlock: invalid address range.");
                return false;
            }

            // Number of 0x0100 blocks touched by the requested range
            int numBlocks = ((lastAddress - firstAddress) / BLOCK_SIZE) + 1;

            // Fresh buffer for this dump
            var packets2 = new List<byte>(numBlocks * BLOCK_SIZE);

            Logger.Write($"ROM EEPROM BIN dump start: 0x{firstAddress:X4} .. 0x{lastAddress:X4}");

            try
            {
                int addr = firstAddress;

                while (addr <= lastAddress)
                {
                    ushort blockBase = (ushort)(addr & 0xFF00);

                    if (DEBUG)
                        Logger.Write($"===== ROM EEPROM block base 0x{blockBase:X4} =====");

                    // Last address we may read inside this current 0x0100 block
                    int blockEnd = blockBase + BLOCK_SIZE - 1;

                    // Do not read past:
                    // 1) requested lastAddress
                    // 2) current block end
                    int maxReadableAbs = Math.Min(lastAddress, blockEnd);

                    while (addr <= maxReadableAbs)
                    {
                        int remaining = maxReadableAbs - addr + 1;
                        byte len = (byte)Math.Min(MAX_CHUNK, remaining);

                        var chunk = ReadRomEeprom((ushort)addr, len);

                        // Safety: if the ECU returns fewer bytes than requested, don't infinite-loop
                        if (chunk == null || chunk.Count == 0)
                        {
                            Logger.Write($"ReadRomEeprom returned 0 bytes at 0x{addr:X4}");
                            return false;
                        }

                        packets2.AddRange(chunk);

                        if (DEBUG)
                            //Logger.Write($"{addr:X4}: " + string.Join(" ", chunk.Select(b => b.ToString("X2"))));

                        // Advance by what was actually received
                        addr += chunk.Count;
                    }

                    // Move to next block if still not finished
                    if (addr <= lastAddress)
                    {
                        addr = blockBase + BLOCK_SIZE;
                    }
                }

                KeepAlive();

                string fileName = $"rom_eeprom_dump_{firstAddress:X4}-{lastAddress:X4}.bin";
                File.WriteAllBytes(fileName, packets2.ToArray());

                Logger.Write($"ROM EEPROM BIN dump done: {packets2.Count} bytes -> {fileName}");
                return true;
            }
            catch (Exception ex)
            {
                Logger.Write($"ReadRomEepromBlock failed: {ex.Message}");
                return false;
            }
        }
        public bool DumpEeprom(int startAddress, int endAddress)
        {
            const ushort BLOCK_SIZE = 0x0100;      // logical block stride
            const ushort VALID_BYTES_PER_BLOCK = 0x00C0; // EEPROM valid region: 0x0000..0x00BF
            const byte MAX_CHUNK = 13;             // protocol limit / safe chunk size

            if (startAddress < 0 || endAddress < 0 || endAddress < startAddress)
            {
                Logger.Write("ReadEepromBlock: invalid address range.");
                return false;
            }

            // Fresh buffer for this dump
            var packets2 = new List<byte>();

            Logger.Write($"EEPROM BIN dump start: 0x{startAddress:X4} .. 0x{endAddress:X4}");

            try
            {
                // Walk absolute address range, but only read valid EEPROM bytes inside each 0x0100 block
                int addr = startAddress;

                while (addr <= endAddress)
                {
                    ushort blockBase = (ushort)(addr & 0xFF00);   // start of current 0x0100 block
                    ushort offsetInBlock = (ushort)(addr & 0x00FF);

                    // If current address is outside valid EEPROM region of this block, skip to next block
                    if (offsetInBlock >= VALID_BYTES_PER_BLOCK)
                    {
                        addr = blockBase + BLOCK_SIZE;
                        continue;
                    }

                    // Last valid absolute address inside this block
                    int blockValidEndAbs = blockBase + VALID_BYTES_PER_BLOCK - 1;

                    // Do not read past:
                    // 1) requested endAddress
                    // 2) valid EEPROM end within this block
                    int maxReadableAbs = Math.Min(endAddress, blockValidEndAbs);

                    while (addr <= maxReadableAbs)
                    {
                        int remaining = maxReadableAbs - addr + 1;
                        byte len = (byte)Math.Min(MAX_CHUNK, remaining);

                        var chunk = ReadEeprom((ushort)addr, len);

                        if (chunk == null || chunk.Count == 0)
                        {
                            Logger.Write($"ReadEeprom returned 0 bytes at 0x{addr:X4}");
                            return false;
                        }

                        packets2.AddRange(chunk);

                        float progress = 1.0f * (addr - startAddress) / (endAddress - startAddress);
                        Logger.Write($"Progress{progress:P1}");
                        //Logger.Write(string.Join(" ", chunk.Select(b => $"0x{b:X2}")));

                        // Safety: advance by what was actually received
                        addr += chunk.Count;
                    }

                    // Move to next block if needed
                    if (addr <= endAddress)
                    {
                        addr = (blockBase + BLOCK_SIZE);
                    }
                }

                KeepAlive();

                string fileName = $"eeprom_dump_{startAddress:X4}-{endAddress:X4}.bin";
                File.WriteAllBytes(fileName, packets2.ToArray());

                Logger.Write($"EEPROM BIN dump done: {packets2.Count} bytes -> {fileName}");
                return true;
            }
            catch (Exception ex)
            {
                Logger.Write($"ReadEepromBlock failed: {ex.Message}");
                return false;
            }
        }
        public bool DumpAllEeprom()
        {
            int startAddress = 0x0000; 
            int endAddress = 0x0000; //0x00BF
            const ushort VALID_BYTES_PER_BLOCK = 0x00C0; // EEPROM valid region: 0x0000..0x00BF
            const byte MAX_CHUNK = 13;             // protocol limit / safe chunk size

            if (startAddress < 0 || endAddress < 0 || endAddress < startAddress)
            {
                Logger.Write("ReadEepromBlock: invalid address range.");
                return false;
            }

            // Fresh buffer for this dump
            var packets2 = new List<byte>();

            Logger.Write($"EEPROM BIN dump start: 0x{startAddress:X4} .. 0x{endAddress:X4}");

            try
            {
                // Walk absolute address range, but only read valid EEPROM bytes inside each 0x0100 block
                int addr = startAddress;

                while (addr <= endAddress)
                {
                    ushort blockBase = (ushort)(addr & 0xFF00);   // start of current 0x0100 block
                    ushort offsetInBlock = (ushort)(addr & 0x00FF);

                    // Last valid absolute address inside this block
                    int blockValidEndAbs = blockBase + VALID_BYTES_PER_BLOCK - 1;

                    // Do not read past:
                    // 1) requested endAddress
                    // 2) valid EEPROM end within this block
                    int maxReadableAbs = Math.Min(endAddress, blockValidEndAbs);

                    while (addr <= maxReadableAbs)
                    {
                        int remaining = maxReadableAbs - addr + 1;
                        byte len = (byte)Math.Min(MAX_CHUNK, remaining);

                        var chunk = ReadEeprom((ushort)addr, len);

                        if (chunk == null || chunk.Count == 0)
                        {
                            Logger.Write($"ReadEeprom returned 0 bytes at 0x{addr:X4}");
                            return false;
                        }

                        packets2.AddRange(chunk);

                        float progress = 1.0f * (addr - startAddress) / (endAddress - startAddress);
                        Logger.Write($"Progress{progress:P1}");
                        //Logger.Write(string.Join(" ", chunk.Select(b => $"0x{b:X2}")));

                        // Safety: advance by what was actually received
                        addr += chunk.Count;
                    }

                }
                packets2.AddRange(new byte[16]);
                packets2.AddRange(Enumerable.Repeat((byte)0xFF, 7));

                var oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x00, 0x82, 0x33 });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                var newbytes = oemzone[0].Body;
                newbytes.RemoveRange(0,4);
                packets2.AddRange(newbytes);

                /*oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x00, 0x00, 0x00 });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x00, 0x9F, 0xFF });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x00, 0xD7, 0x01 });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x00, 0xFF, 0xFC });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                packets2.AddRange(newbytes);*/

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x01, 0x6A, 0x89 });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                newbytes.RemoveRange(0, 4);
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x02, 0x2E, 0x10 });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                newbytes.RemoveRange(0, 4);
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x03, 0xFF, 0xFF });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                newbytes.RemoveRange(0, 4);
                packets2.AddRange(newbytes);

                oemzone = SendCustom(new List<byte> { 0x18, 0x00, 0x04, 0xC7, 0xAE });
                oemzone = oemzone.Where(b => !b.IsAckNak).ToList();
                newbytes = oemzone[0].Body;
                newbytes.RemoveRange(0, 4);

                packets2.AddRange(newbytes);

                KeepAlive();

                string fileName = $"eeprom_dump_{startAddress:X4}-{0x00FF:X4}.bin";
                File.WriteAllBytes(fileName, packets2.ToArray());

                Logger.Write($"EEPROM BIN dump done: {packets2.Count} bytes -> {fileName}");
                return true;
            }
            catch (Exception ex)
            {
                Logger.Write($"ReadEepromBlock failed: {ex.Message}");
                return false;
            }
        }